package com.example.order.config;

import com.example.order.service.InventoryApiService;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import feign.Feign;
import feign.Target;
import feign.hystrix.HystrixFeign;
import feign.hystrix.SetterFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

@Configuration
public class DefaultHystrixConfig {
    @Bean
    public Feign.Builder feignHystrixBuilder() {
        return HystrixFeign.builder().setterFactory(new SetterFactory() {
            @Override
            public HystrixCommand.Setter create(Target<?> target, Method method) {
                return HystrixCommand.Setter
                        // 控制 InventoryApiService 下,所有方法的Hystrix Configuration
                        .withGroupKey(HystrixCommandGroupKey.Factory.asKey(InventoryApiService.class.getSimpleName()))
                        .andCommandPropertiesDefaults(buildDefaultCommandProperties())
                        //线程池为30
                        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(30));
            }
        });

    }

    private HystrixCommandProperties.Setter buildDefaultCommandProperties() {
        return HystrixCommandProperties.Setter()
                //实行超时
                .withExecutionTimeoutInMilliseconds(5000)
                // 启用断路器
                .withCircuitBreakerEnabled(true)
                //10秒钟内至少2此请求失败，熔断器才发挥起作用
                .withCircuitBreakerRequestVolumeThreshold(2)
                //错误率达到50开启熔断保护
                .withCircuitBreakerErrorThresholdPercentage(50)
                //熔断器中断请求50秒后会进入半打开状态,放部分流量过去重试
                .withCircuitBreakerSleepWindowInMilliseconds(5000)
                //想线程池隔离策略 THREAD 线程池隔离 SEMAPHORE 信号量隔离
                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                //  启动fallback(降级), 你需要配置好fallback方法才设置为true; dont override unless you also override ApiCommand to have a fallback
                .withFallbackEnabled(true)
                /**
                 *  我也不懂, 复制过来的..
                 * 设置每个bucket的请求执行次数被保存的最大数量，如果再一个bucket内，执行次数超过了这个值，那么就会重新覆盖从bucket的开始再写
                 * 举例来说，如果bucket size设置为100，而且每个bucket代表一个10秒钟的窗口，但是在这个bucket内发生了500次请求执行，那么这个bucket内仅仅会保留100次执行
                 * 如果调大这个参数，就会提升需要耗费的内存，来存储相关的统计值，不允许热修改
                 * 默认值是100
                 */
                .withMetricsRollingPercentileBucketSize(10000)
                .withMetricsRollingPercentileEnabled(true);
    }

}
